package com.note.redisLock.redLock;

/**
 * @ClassName RedissonAutoConfiguration
 * @Description TODO
 * @Author QiBin
 * @Date 2020/6/1010:51
 * @Version 1.0
 **/

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import jodd.util.StringUtil;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.Resource;


/**
 * @author chendesheng
 * @create 2019/10/12 10:50
 */
//@Configuration
//@ConditionalOnClass(Config.class)
//@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {

    @Resource
    private RedissonProperties redissonProperties;

    /**
     * 哨兵模式自动装配
     * @return
     */
    @Bean
    @ConditionalOnProperty(name="redisson.master-name")
    RedissonClient redissonSentinel() {
        Config config = new Config();
        SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redissonProperties.getSentinelAddresses())
                .setMasterName(redissonProperties.getMasterName())
                .setTimeout(redissonProperties.getTimeout())
                .setMasterConnectionPoolSize(redissonProperties.getMasterConnectionPoolSize())
                .setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize());

        if(StringUtil.isNotBlank(redissonProperties.getPassword())) {
            serverConfig.setPassword(redissonProperties.getPassword());
        }
        return Redisson.create(config);
    }

    /**
     * 单机模式自动装配
     * @return
     */
    @Bean
    @ConditionalOnProperty(name="redisson.address")
    RedissonClient redissonSingle() {
        Config config = new Config();
        SingleServerConfig serverConfig = config.useSingleServer()
                .setAddress(redissonProperties.getAddress())
                .setTimeout(redissonProperties.getTimeout())
                .setConnectionPoolSize(redissonProperties.getConnectionPoolSize())
                .setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());

        if(StringUtil.isNotBlank(redissonProperties.getPassword())) {
            serverConfig.setPassword(redissonProperties.getPassword());
        }

        return Redisson.create(config);
    }




    /**
     * 装配locker类，并将实例注入到RedissLockUtil中
     * @return
     */
    @Bean
    DistributedLocker distributedLocker(RedissonClient redissonClient) {
        DistributedLocker locker = new RedissonDistributedLocker();
        ((RedissonDistributedLocker) locker).setRedissonClient(redissonClient);
        RedissonLockUtil.setLocker(locker);
        return locker;
    }
    //============分割线===========
//    @Value("${spring.redis.user.database}")
//    private int userDB;
//    @Value("${spring.redis.basic.database}")
//    private int basicDB;
//    @Value("${spring.redis.auction.database}")
//    private int auctionDB;
//    @Value("${spring.redis.default.database}")
    private int defaultDB = 3;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.password}")
    private String pwd;
    @Value("${spring.redis.sentinel.master}")
    private String master;
    @Value("${spring.redis.sentinel.nodes}")
    private String nodes;

    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 最大建立连接等待时间
        jedisPoolConfig.setMaxWaitMillis(3600);
        // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
//        jedisPoolConfig.setMinEvictableIdleTimeMillis(1800000);
        // 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
        jedisPoolConfig.setNumTestsPerEvictionRun(3);
        // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(-1);
        // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
        jedisPoolConfig.setTestOnBorrow(true);
        // 在空闲时检查有效性, 默认false
        jedisPoolConfig.setTestWhileIdle(false);
        return jedisPoolConfig;
    }

    public JedisConnectionFactory defaultRedisConnectionFactory(int db){
        return getJedisConnectionFactory(db, nodes, master, pwd);
    }

    private JedisConnectionFactory getJedisConnectionFactory(int db, String nodes, String master, String pwd) {
        String[] split = nodes.split(",");
        RedisSentinelConfiguration redisSentinelConfiguration = new RedisSentinelConfiguration();
        for (int i = 0; i < split.length; i++) {
            String[] node = split[i].split(":");
            RedisNode redisNode = new RedisNode(node[0], Integer.parseInt(node[1]));
            redisNode.setName(master);
            redisSentinelConfiguration.addSentinel(redisNode);
        }
        redisSentinelConfiguration.setDatabase(db);
        redisSentinelConfiguration.setMaster(master);
        redisSentinelConfiguration.setPassword(RedisPassword.of(pwd));
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisSentinelConfiguration);
        //TODO :重要
        jedisConnectionFactory.afterPropertiesSet();

        return jedisConnectionFactory;
    }

    public RedisTemplate defaultRedisTemplate(int db){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer(Object.class));
        redisTemplate.setValueSerializer(new FastJsonRedisSerializer(Object.class));
        redisTemplate.setConnectionFactory(defaultRedisConnectionFactory(db));
        return redisTemplate;
    }

//    @Bean(name = "userRedisTemplate")
//    public RedisTemplate userRedis() {
//        return defaultRedisTemplate(userDB);
//    }
//
//    @Bean(name = "basicRedisTemplate")
//    public RedisTemplate basicRedis() {
//        return defaultRedisTemplate(basicDB);
//    }
//
//    @Bean(name = "auctionRedisTemplate")
//    public RedisTemplate auctionRedis() {
//        return defaultRedisTemplate(auctionDB);
//    }

    @Bean(name = "redisTemplate")
    public RedisTemplate redis() {
        return defaultRedisTemplate(defaultDB);
    }


}
